/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <flgrCoreData.h>
#include <flgrCoreDataIO.h>
#include <flgrCoreDispatch.h>
#include <flgrCoreMalloc.h>
#include "flgrCoreCompare.h"
#include "flgrCoreCompareFast.h"

/*!
 * \defgroup group_fulguro_core_compare Compare and replace functions
 * \ingroup group_fulguro_core
 * \brief Functions to compare FLGR_DataXD or to replace element inside an array
 * @{
 */



//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// 1D COMPARE FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////


FLGR_Test flgr_get_test_value(char *test) {
  FLGR_DECLARE_FUNCTION;
  
  if(strlen(test)==0) {
    POST_ERROR("empty test not allowed !\n");
    return  FLGR_TEST_UNKNOWN;
  }

  if(strcmp(test,"<")==0) {
    return FLGR_TEST_INF;

  }else if(strcmp(test,"<=")==0) {
    return FLGR_TEST_INFEQ;

  }else if(strcmp(test,"==")==0) {
    return FLGR_TEST_EQ;

  }else if(strcmp(test,">=")==0) {
    return FLGR_TEST_SUPEQ;

  }else if(strcmp(test,">")==0) {
    return FLGR_TEST_SUP;

  }else if(strcmp(test,"!=")==0) {
    return FLGR_TEST_DIFF;

  }else {
    POST_ERROR("test ""%s"" unknown !\n",test);
    return FLGR_TEST_UNKNOWN;
  }

}



////////////////////////////////////////////////////////////////////////////
// Macro for different type of flgr1d_compare
////////////////////////////////////////////////////////////////////////////
#define FLGR_MACRO_COMPARE_1D(dtype)			\
  dtype *ptrt1 = (dtype*) dat1->array;			\
  dtype *ptrt2 = (dtype*) dat2->array;			\
  dtype v1,v2;						\
  int i,length = dat1->length*dat1->spp;		\
							\
  FLGR_DECLARE_FUNCTION;				\
							\
  switch(test) {					\
  case FLGR_TEST_INF:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      v2 = flgr1d_get_data_array_##dtype(ptrt2,i);	\
      if( v1<v2 ) {}					\
      else return FLGR_FALSE;				\
    }							\
    break;						\
							\
  case FLGR_TEST_INFEQ:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      v2 = flgr1d_get_data_array_##dtype(ptrt2,i);	\
      if( v1<=v2 ) {}					\
      else return FLGR_FALSE;				\
    }							\
    break;						\
    							\
  case FLGR_TEST_EQ:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      v2 = flgr1d_get_data_array_##dtype(ptrt2,i);	\
      if( v1==v2 ) {} 					\
      else return FLGR_FALSE;				\
    }							\
    break;						\
							\
  case FLGR_TEST_SUPEQ:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      v2 = flgr1d_get_data_array_##dtype(ptrt2,i);	\
      if( v1>=v2 ) {} 					\
      else return FLGR_FALSE;				\
    }							\
    break;						\
							\
  case FLGR_TEST_SUP:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      v2 = flgr1d_get_data_array_##dtype(ptrt2,i);	\
      if( v1>v2 ) {} 					\
      else return FLGR_FALSE;				\
    }							\
    break;						\
							\
  case FLGR_TEST_DIFF:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      v2 = flgr1d_get_data_array_##dtype(ptrt2,i);	\
      if( v1!=v2 ) {} 					\
      else return FLGR_FALSE;				\
    }							\
    break;						\
  default:						\
    return FLGR_FALSE;					\
  }							\
							\
  return FLGR_TRUE

int flgr1d_compare_fgBIT(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Data1D *dat2) {
  FLGR_MACRO_COMPARE_1D(fgBIT);
}
int flgr1d_compare_fgUINT8(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  if(test == FLGR_TEST_EQ) {
    return flgr1d_compare_eq_fast_fgUINT8(dat1,dat2);
  }else {
    FLGR_MACRO_COMPARE_1D(fgUINT8);
  }
#else
  FLGR_MACRO_COMPARE_1D(fgUINT8);
#endif
}
int flgr1d_compare_fgUINT16(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  if(test == FLGR_TEST_EQ) {
    return flgr1d_compare_eq_fast_fgUINT16(dat1,dat2);
  }else {
    FLGR_MACRO_COMPARE_1D(fgUINT16);
  }
#else
  FLGR_MACRO_COMPARE_1D(fgUINT16);
#endif
}
int flgr1d_compare_fgUINT32(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  if(test == FLGR_TEST_EQ) {
    return flgr1d_compare_eq_fast_fgUINT32(dat1,dat2);
  }else {
    FLGR_MACRO_COMPARE_1D(fgUINT32);
  }
#else
  FLGR_MACRO_COMPARE_1D(fgUINT32);
#endif
}
int flgr1d_compare_fgINT8(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  if(test == FLGR_TEST_EQ) {
    return flgr1d_compare_eq_fast_fgINT8(dat1,dat2);
  }else {
    FLGR_MACRO_COMPARE_1D(fgINT8);
  }
#else
  FLGR_MACRO_COMPARE_1D(fgINT8);
#endif
}
int flgr1d_compare_fgINT16(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  if(test == FLGR_TEST_EQ) {
    return flgr1d_compare_eq_fast_fgINT16(dat1,dat2);
  }else {
    FLGR_MACRO_COMPARE_1D(fgINT16);
  }
#else
  FLGR_MACRO_COMPARE_1D(fgINT16);
#endif
}
int flgr1d_compare_fgINT32(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Data1D *dat2) {
#ifdef __SSE2__
  if(test == FLGR_TEST_EQ) {
    return flgr1d_compare_eq_fast_fgINT32(dat1,dat2);
  }else {
    FLGR_MACRO_COMPARE_1D(fgINT32);
  }
#else
  FLGR_MACRO_COMPARE_1D(fgINT32);
#endif
}
int flgr1d_compare_fgFLOAT32(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Data1D *dat2) {
  FLGR_MACRO_COMPARE_1D(fgFLOAT32);
}
int flgr1d_compare_fgFLOAT64(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Data1D *dat2) {
  FLGR_MACRO_COMPARE_1D(fgFLOAT64);
}

//////////////////////////////////////////////////////////////////
/*! Compare element by element two FLGR_Data1D
 *
 *  ex: dat1==dat2, dat1>dat2...
 *  @warning dat1!=dat2 is not equivalent to !(dat1==dat2). The dat1!=dat2 test returns true if and only if
 *  every values are differents. The !(dat1==dat2) return true if at least one value is different.
 *
 *  @param dat1 : pointer to FLGR_Data1D structure
 *  @param test : String for test ">"  "<"  ">="  "<="  "=="  "!="
 *  @param dat2 : pointer to FLGR_Data1D structure
 *  @returns FLGR_TRUE or FLGR_FALSE
 */
//////////////////////////////////////////////////////////////////
int flgr1d_compare(FLGR_Data1D *dat1, char * test, FLGR_Data1D *dat2) {
  FLGR_Test tst;

  FLGR_DECLARE_FUNCTION;

  if((dat1==NULL) || (dat2==NULL)) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if(flgr1d_is_data_same_attributes(dat1, dat2, __FUNCTION__)!=FLGR_RET_OK) {
    POST_ERROR("Size or Type different\n");
    return FLGR_FALSE;
  }

  tst=flgr_get_test_value(test);
  if(tst==FLGR_TEST_UNKNOWN) {
    POST_ERROR("Illegal test %s",test);
    return FLGR_FALSE;
  }

  switch(dat1->type) {
  case FLGR_BIT:
    return flgr1d_compare_fgBIT(dat1,tst,dat2);

  case FLGR_UINT8:
    return flgr1d_compare_fgUINT8(dat1,tst,dat2);

  case FLGR_UINT16:
    return flgr1d_compare_fgUINT16(dat1,tst,dat2);

  case FLGR_UINT32:
    return flgr1d_compare_fgUINT32(dat1,tst,dat2);

  case FLGR_INT8:
    return flgr1d_compare_fgINT8(dat1,tst,dat2);

  case FLGR_INT16:
    return flgr1d_compare_fgINT16(dat1,tst,dat2);

  case FLGR_INT32:
    return flgr1d_compare_fgINT32(dat1,tst,dat2);

  case FLGR_FLOAT32:
    return flgr1d_compare_fgFLOAT32(dat1,tst,dat2);

  case FLGR_FLOAT64:
    return flgr1d_compare_fgFLOAT64(dat1,tst,dat2);

  default:
    POST_ERROR("type unknown!\n");
    return FLGR_FALSE;
  }
}







////////////////////////////////////////////////////////////////////////////
// Macro for different type of flgr1d_compare
////////////////////////////////////////////////////////////////////////////
#define FLGR_MACRO_COMPARE_CONST_1D(dtype)		\
  dtype *ptrt1 = (dtype*) dat1->array;			\
  dtype *ptrt2 = (dtype*) constant->array;		\
  dtype v1;						\
  int spp  = dat1->spp;					\
  int i,length = dat1->length*dat1->spp;		\
							\
  FLGR_DECLARE_FUNCTION;				\
							\
  switch(test) {					\
  case FLGR_TEST_INF:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      if( v1<flgr_get_array_##dtype(ptrt2,i%spp) ) {}	\
      else return FLGR_FALSE;				\
    }							\
    break;						\
							\
  case FLGR_TEST_INFEQ:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      if( v1<=flgr_get_array_##dtype(ptrt2,i%spp) ) {}	\
      else return FLGR_FALSE;				\
    }							\
    break;						\
							\
  case FLGR_TEST_EQ:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      if( v1==flgr_get_array_##dtype(ptrt2,i%spp) ) {}	\
      else return FLGR_FALSE;				\
    }							\
    break;						\
							\
  case FLGR_TEST_SUPEQ:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      if( v1>=flgr_get_array_##dtype(ptrt2,i%spp) ) {}	\
      else return FLGR_FALSE;				\
    }							\
    break;						\
							\
  case FLGR_TEST_SUP:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      if( v1>flgr_get_array_##dtype(ptrt2,i%spp) ) {}	\
      else return FLGR_FALSE;				\
    }							\
    break;						\
							\
  case FLGR_TEST_DIFF:					\
    for(i=0 ; i<length ; i++) {				\
      v1 = flgr1d_get_data_array_##dtype(ptrt1,i);	\
      if( v1!=flgr_get_array_##dtype(ptrt2,i%spp) ) {}	\
      else return FLGR_FALSE;				\
    }							\
    break;						\
							\
  default:						\
    return FLGR_FALSE;					\
  }							\
							\
  return FLGR_TRUE

int flgr1d_compare_const_fgBIT(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_1D(fgBIT);
}
int flgr1d_compare_const_fgUINT8(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_1D(fgUINT8);
}
int flgr1d_compare_const_fgUINT16(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_1D(fgUINT16);
}
int flgr1d_compare_const_fgUINT32(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_1D(fgUINT32);
}
int flgr1d_compare_const_fgINT8(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_1D(fgINT8);
}
int flgr1d_compare_const_fgINT16(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_1D(fgINT16);
}
int flgr1d_compare_const_fgINT32(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_1D(fgINT32);
}
int flgr1d_compare_const_fgFLOAT32(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_1D(fgFLOAT32);
}
int flgr1d_compare_const_fgFLOAT64(FLGR_Data1D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_1D(fgFLOAT64);
}

//////////////////////////////////////////////////////////////////
/*! Compare element by element a FLGR_Data1D and a constant
 *
 *  @warning dat1!=constant is not equivalent to !(dat1==constant).
 *  The dat1!=constant test returns true if and only if
 *  every values are differents. The !(dat1==constant) return true if at least one value is different.
 *
 *  @param dat1 : pointer to FLGR_Data1D structure
 *  @param test : String for test ">"  "<"  ">="  "<="  "=="  "!="
 *  @param constant : pointer to a value (type must correspond to dat1->type)
 *  @returns FLGR_TRUE or FLGR_FALSE
 */
//////////////////////////////////////////////////////////////////
int flgr1d_compare_const_ptr(FLGR_Data1D *dat1, char * test, FLGR_Vector *constant) {
  FLGR_Test tst;

  FLGR_DECLARE_FUNCTION;

  if(dat1==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  tst=flgr_get_test_value(test);
  if(tst==FLGR_TEST_UNKNOWN) {
    POST_ERROR("Illegal test %s",test);
    return FLGR_FALSE;
  }

  if(dat1->spp != constant->spp) {
    POST_ERROR("Vector size don't correspond\n");
    return FLGR_RET_UNDEFINED_ERROR;
  }

  FLGR_DISPATCH_FUNCTION(FLGR_RET_TYPE_UNKNOWN, dat1->type, flgr1d_compare_const, dat1, tst, constant);
}


//////////////////////////////////////////////////////////////////
/*! Compare element by element a FLGR_Data1D and a constant
 *
 *  @warning dat1!=constant is not equivalent to !(dat1==constant).
 *  The dat1!=constant test returns true if and only if
 *  every values are differents. The !(dat1==constant) return true if at least one value is different.
 *  @param dat1 : pointer to FLGR_Data1D structure
 *  @param test : String for test ">"  "<"  ">="  "<="  "=="  "!="
 *  @param constant : pointer to a string
 *  @returns FLGR_TRUE or FLGR_FALSE
 */
//////////////////////////////////////////////////////////////////
int flgr1d_compare_const_str(FLGR_Data1D *dat1, char * test, char *constant) {
  int ret;
  FLGR_Vector *vector_constant;

  FLGR_DECLARE_FUNCTION;

  if(dat1==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  vector_constant = flgr_vector_create(dat1->spp,dat1->type);

  if((ret=flgr_vector_import_string(vector_constant, constant))
     != FLGR_RET_OK) {

    POST_ERROR("String is not valid ""%s""\n",constant);
    flgr_vector_destroy(vector_constant);
    return ret;
  }

  ret = flgr1d_compare_const_ptr(dat1, test, vector_constant);

  flgr_vector_destroy(vector_constant);

  return ret;
}


 
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// 2D COMPARE FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////




///////////////////////////////////////////////////////////////////////////
// Macro for different type of flgr2d_compare
///////////////////////////////////////////////////////////////////////////
#define FLGR_MACRO_COMPARE_2D(dtype)		\
  FLGR_Data1D **p1 = dat1->row;			\
  FLGR_Data1D **p2 = dat2->row;			\
  int i;					\
  int ret;					\
						\
  FLGR_DECLARE_FUNCTION;			\
						\
  for(i=0 ; i<dat1->size_y ; i++,p1++,p2++) {	\
    ret = flgr1d_compare_##dtype(*p1,test,*p2);	\
    if(ret==FLGR_FALSE)	return FLGR_FALSE;	\
  }						\
						\
  return FLGR_TRUE

int flgr2d_compare_fgBIT(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Data2D *dat2) {
  FLGR_MACRO_COMPARE_2D(fgBIT);
}
int flgr2d_compare_fgUINT8(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Data2D *dat2) {
  FLGR_MACRO_COMPARE_2D(fgUINT8);
}
int flgr2d_compare_fgUINT16(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Data2D *dat2) {
  FLGR_MACRO_COMPARE_2D(fgUINT16);
}
int flgr2d_compare_fgUINT32(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Data2D *dat2) {
  FLGR_MACRO_COMPARE_2D(fgUINT32);
}
int flgr2d_compare_fgINT8(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Data2D *dat2) {
  FLGR_MACRO_COMPARE_2D(fgINT8);
}
int flgr2d_compare_fgINT16(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Data2D *dat2) {
  FLGR_MACRO_COMPARE_2D(fgINT16);
}
int flgr2d_compare_fgINT32(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Data2D *dat2) {
  FLGR_MACRO_COMPARE_2D(fgINT32);
}
int flgr2d_compare_fgFLOAT32(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Data2D *dat2) {
  FLGR_MACRO_COMPARE_2D(fgFLOAT32);
}
int flgr2d_compare_fgFLOAT64(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Data2D *dat2) {
  FLGR_MACRO_COMPARE_2D(fgFLOAT64);
}


//////////////////////////////////////////////////////////////////
/*! Compare two images pixels by pixels.
 *  @warning dat1!=dat2 is not equivalent to !(dat1==dat2). The dat1!=dat2 test returns true if and only if
 *  every values are differents. The !(dat1==dat2) return true if at least one value is different.
 *  @param dat1 : pointer to FLGR_Data2D structure
 *  @param test : String for test ">"  "<"  ">="  "<="  "=="  "!="
 *  @param dat2 : pointer to FLGR_Data2D structure
 *  @returns FLGR_TRUE or FLGR_FALSE
 */
//////////////////////////////////////////////////////////////////
int flgr2d_compare(FLGR_Data2D *dat1, char * test, FLGR_Data2D *dat2) {
  FLGR_Test tst;

  FLGR_DECLARE_FUNCTION;

  if((dat1==NULL) || (dat2==NULL)) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if(flgr2d_is_data_same_attributes(dat2, dat1, __FUNCTION__)!=0) {
    POST_ERROR("Size are different\n");
    return FLGR_FALSE;
  }

  tst=flgr_get_test_value(test);
  if(tst<0) {
    POST_ERROR("Illegal test %s",test);
    return FLGR_FALSE;
  }


  if(dat1->type==FLGR_UINT8) {
    return flgr2d_compare_fgUINT8(dat1,tst,dat2);

  }else if(dat1->type==FLGR_UINT16) {
    return flgr2d_compare_fgUINT16(dat1,tst,dat2);

  }else if(dat1->type==FLGR_UINT32) {
    return flgr2d_compare_fgUINT32(dat1,tst,dat2);

  }else if(dat1->type==FLGR_INT8) {
    return flgr2d_compare_fgINT8(dat1,tst,dat2);

  }else if(dat1->type==FLGR_INT16) {
    return flgr2d_compare_fgINT16(dat1,tst,dat2);

  }else if(dat1->type==FLGR_INT32) {
    return flgr2d_compare_fgINT32(dat1,tst,dat2);

  }else if(dat1->type==FLGR_FLOAT32) {
    return flgr2d_compare_fgFLOAT32(dat1,tst,dat2);

  }else if(dat1->type==FLGR_FLOAT64) {
    return flgr2d_compare_fgFLOAT64(dat1,tst,dat2);

  }else if(dat1->type==FLGR_BIT) {
    return flgr2d_compare_fgBIT(dat1,tst,dat2);

  }else {
    POST_ERROR("type unknown!\n");
    return FLGR_FALSE;
  }

}




///////////////////////////////////////////////////////////////////////////
// Macro for different type of flgr2d_compare
///////////////////////////////////////////////////////////////////////////
#define FLGR_MACRO_COMPARE_CONST_2D(dtype)				\
  FLGR_Data1D **p1 = dat1->row;						\
  int i,ret;								\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  for(i=0 ; i<dat1->size_y ; i++,p1++) {				\
    ret = flgr1d_compare_const_##dtype(*p1,test,constant);		\
    if(ret==FLGR_FALSE)	return FLGR_FALSE;				\
  }									\
									\
  return FLGR_TRUE


int flgr2d_compare_const_fgBIT(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_2D(fgBIT);
}
int flgr2d_compare_const_fgUINT8(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_2D(fgUINT8);
}
int flgr2d_compare_const_fgUINT16(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_2D(fgUINT16);
}
int flgr2d_compare_const_fgUINT32(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_2D(fgUINT32);
}
int flgr2d_compare_const_fgINT8(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_2D(fgINT8);
}
int flgr2d_compare_const_fgINT16(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_2D(fgINT16);
}
int flgr2d_compare_const_fgINT32(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_2D(fgINT32);
}
int flgr2d_compare_const_fgFLOAT32(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_2D(fgFLOAT32);
}
int flgr2d_compare_const_fgFLOAT64(FLGR_Data2D *dat1, FLGR_Test test, FLGR_Vector *constant) {
  FLGR_MACRO_COMPARE_CONST_2D(fgFLOAT64);
}


//////////////////////////////////////////////////////////////////
/*! Compare all pixels of an images with a constant.
 *
 *  @warning dat1!=constant is not equivalent to !(dat1==constant).
 *  The dat1!=constant test returns true if and only if
 *  every values are differents. The !(dat1==constant) return true if at least one value is different.
 *
 *  @param dat1 : pointer to FLGR_Data2D structure
 *  @param test : String for test ">"  "<"  ">="  "<="  "=="  "!="
 *  @param constant : void pointer to constant variable (type must correspond to image type)
 *  @returns FLGR_TRUE or FLGR_FALSE
 */
//////////////////////////////////////////////////////////////////
int flgr2d_compare_const_ptr(FLGR_Data2D *dat1, char * test, FLGR_Vector *constant) {
  FLGR_Test tst;

  FLGR_DECLARE_FUNCTION;

  if(dat1==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  tst=flgr_get_test_value(test);
  if(tst<0) {
    POST_ERROR("Illegal test %s",test);
    return FLGR_FALSE;
  }

  FLGR_DISPATCH_FUNCTION( FLGR_RET_TYPE_UNKNOWN, dat1->type,flgr2d_compare_const,dat1,tst,constant);
}




//////////////////////////////////////////////////////////////////
/*! Compare FLGR_Data2D elements with a constant.
 *
 *  @warning dat1!=constant is not equivalent to !(dat1==constant).
 *  The dat1!=constant test returns true if and only if
 *  every values are differents. The !(dat1==constant) return true if at least one value is different.
 *
 *  @param dat1 : pointer to FLGR_Data2D structure
 *  @param test : String for test ">"  "<"  ">="  "<="  "=="  "!="
 *  @param constant : void pointer to constant variable (type must correspond to image type)
 *  @returns FLGR_TRUE or FLGR_FALSE
 */
//////////////////////////////////////////////////////////////////
int flgr2d_compare_const_str(FLGR_Data2D *dat1, char *test, char *constant) {
  int ret;
  FLGR_Vector *vector_constant;

  FLGR_DECLARE_FUNCTION;

  if(dat1==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  vector_constant = flgr_vector_create(dat1->spp,dat1->type);

  if((ret=flgr_vector_import_string(vector_constant, constant))
     != FLGR_RET_OK) {

    POST_ERROR("String is not valid ""%s""\n",constant);
    flgr_vector_destroy(vector_constant);
    return ret;
  }

  ret = flgr2d_compare_const_ptr(dat1, test, vector_constant);

  flgr_vector_destroy(vector_constant);

  return ret;
}




//! @}
